#pragma once
#include "Common.hpp"
#include "Loop.hpp"

class Channel{
public:
    using EventCallback = std::function<void()>; // 注意: 这里不能放在 private 中, 否则会报错
    // explicit Channel(Poller* poller, int fd):_fd(fd),_events(0),_revents(0),_poller(poller){} // 显式调用 
    explicit Channel(EventLoop *loop, int fd):_fd(fd), _events(0), _revents(0), _loop(loop) {} 

    ~Channel(){
        if (_fd != -1) {
            close(_fd);
            _fd = -1; // 避免重复关闭
        }
    }
    Channel(const Channel&) = delete;
    Channel& operator=(const Channel&) = delete;

    int Fd() const {return _fd;}
    uint32_t Events() const {return _events;}

    // 判断当前事件是否可读写
    bool ReadAble() const { return (_events & EPOLLIN);  }
    bool WriteAble() const { return (_events & EPOLLOUT);}
    
    // 设置回调函数
    void SetReadCallback(const EventCallback& cb) {_read_callback = cb;}
    void SetWriteCallback(const EventCallback& cb){_write_callback = cb;}
    void SetCloseCallback(const EventCallback& cb){_close_callback = cb;}
    void SetErrorCallback(const EventCallback& cb){_error_callback = cb;}
    void SetEventCallback(const EventCallback& cb){_event_callback = cb;}
    /* 监控事件开关 -- 进行事件监控连接后, 描述符就绪事件, 设置实际就绪事件*/
    void SetREvents(uint32_t events){ _revents = events;}
    

    /* 开启事件监控 */
    void EnableRead(){ _events |= EPOLLIN; Update();}
    void EnableWrite(){ _events |= EPOLLOUT; Update();}

    /* 关闭事件监控 */
    void DisableRead(){ _events &= ~EPOLLIN; Update();}
    void DisableWrite(){ _events &= ~EPOLLOUT; Update();} 
    void DisableAll(){_events = 0; Update();} // 关闭所有事件

    /* 后面调用 EventLoop 接口来移除事件监控 */
    void Remove(); // 移除事件
    void Update(); // 更新事件
    
    void HandleEvent(){ // 处理事件, 判断连接触发了什么事件  
        // 实际项目中, 连接断开并不会直接先断开, 还是看到是否有数据可读, 先读完数据或者发送出错再断开
        if((_revents & EPOLLIN) || (_revents & EPOLLRDHUP) || (_revents & EPOLLPRI)){
            // 不管任何事件, 都会调用的回调函数
            if(_event_callback) _event_callback();
            if(_read_callback) _read_callback();
        }
        else if(_revents & EPOLLOUT){
            // 不管任何事件, 都会调用的回调函数
            if(_event_callback) _event_callback(); 
            if(_write_callback) _write_callback();
        }
        else if(_revents & EPOLLERR){
            if(_error_callback) _error_callback();
        }
        else if(_revents & EPOLLHUP){
            if(_close_callback) _close_callback();
        }
        // if(_event_callback) _event_callback(); // 任意事件回调
    }
private:
    int _fd; // 事件对应的文件描述符
    uint32_t _events; // 当前需要监控的事件
    uint32_t _revents; // 当前连接触发的事件
    // Poller* _poller; // 事件循环
    EventLoop* _loop;

    EventCallback _read_callback;   // 读事件回调
    EventCallback _write_callback;  // 写事件回调
    EventCallback _close_callback;  // 关闭事件回调
    EventCallback _error_callback;  // 错误事件回调
    EventCallback _event_callback;  // 任意事件回调
};

void Channel::Remove(){return _loop->RemoveEvent(this); } // 移除事件
void Channel::Update(){return _loop->UpdateEvent(this);} // 更新事件
